package com.apes.oap.request.converter;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * 功能：
 *
 * @author xul
 * @create 2018-09-04 17:09
 */

public class RopHttpMessageConverter {

    private static List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();

    static {
        //messageConverters.add(new FormMessageConverter());
        messageConverters.add(new JsonMessageConverter());
        messageConverters.add(new StringMessageConverter());
    }

    public static HashMap<String, String> read(HttpServletRequest servletRequest)  {
        try {
            return read(servletRequest, HashMap.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T read(HttpServletRequest servletRequest, Class<T> responseClass) throws Exception {
        ServletServerHttpRequest httpRequest = new ServletServerHttpRequest(servletRequest);
        if (!hasMessageBody(httpRequest.getHeaders())) {  // || hasEmptyMessageBody(httpInputMessage)
            return null;
        }
        MediaType contentType = getContentType(httpRequest.getHeaders());
        for (HttpMessageConverter<?> messageConverter : messageConverters) {
            if (responseClass != null) {
                if (messageConverter.canRead(responseClass, contentType)) {
                    HttpInputMessage httpInputMessage = new MappingInputMessage(httpRequest.getBody(), httpRequest.getHeaders());
                    return (T) messageConverter.read((Class) responseClass, httpInputMessage);
                }
            }
        }
//        throw new RuntimeException("Could not extract response: no suitable RopHttpMessageConverter found " +
//                "for response type [" + responseClass + "] and content type [" + contentType + "]");
        return null;
    }

    public static boolean hasMessageBody(HttpHeaders headers) {
        if (headers.getContentLength() == 0) {
            return false;
        }
        return true;
    }

    public static boolean hasEmptyMessageBody(HttpInputMessage response) throws Exception {
        InputStream body = response.getBody();
        if (body == null) {
            return true;
        } else if (body.markSupported()) {
            body.mark(1);
            if (body.read() == -1) {
                return true;
            } else {
                body.reset();
                return false;
            }
        } else {
            PushbackInputStream pushbackInputStream = new PushbackInputStream(body);
            int b = pushbackInputStream.read();
            if (b == -1) {
                return true;
            } else {
                pushbackInputStream.unread(b);
                return false;
            }
        }
    }

    private static MediaType getContentType(HttpHeaders headers) {
        MediaType contentType = headers.getContentType();
        if (contentType == null) {
            contentType = MediaType.APPLICATION_JSON_UTF8;
        }
        return contentType;
    }
}
